.NET Framework History version 1 - 2002 version 2 - 2005, major version, suppored by Visual Studio 2005 version 3 - 2006 version 3.5 - 2007, suppored by Visual Studio 2008 version 4 - 2010, major version, suppored by Visual Studio 2010 General Information assembly - a collection of classes (.exe if Main method defined, .dll if no Main method defined) other .NET languages: C#, VB.NET, C++, P#, Prolog.NET F# * .NET implementation of OCaml (most notable language of the ML language family); * version 1.0 circa 2005, current version is 2.0 circa 2010 * strongly typed with type inference * contains pattern matching, interactive scripting and debugging, OO, higher-order functions object-oriented and functional programming can be mixed freely * F# has access to .NET libraries and methods * F# libraries and methods can be exposed to other .NET applications * open - aka include * () are optional behind no-argument function definitions and calls * ; - is used as separator * all values have a type (strongly-typed) that can be infered by the compiler * code is just typed in, indentation is very important * operates on values - inmutable objects, "let" is the keyword for deignation value definitions, functions are also values * FSI - F# Interactive is an immediate evaluator for F# expressions (read/eval/print loop), use ;; in FSI to terminate commands * the last expression evaluated is returned as the output of functions * ( and ) are used for prioritization and are not needed for enclosing arguments * partial application and composition are the major functional programming tools in F#, they allow to use functions as building blocks to create new constructs * printfn "%A" - handy printing function MODULES / NAMESPACES * code organization structure * a file can contaim many modules * a module has to be contained in one file format specifiers: %d - int %g, %G - float %f - float or double %c - char %s - string operators: include the standard ones as in C# and Java % - modulo + - concatenation for strings not - logical negation for boolean &&& - bitwise for int ||| - bitwise for int ^^^ - bitwise for int <<< - bitwise for int >>> - bitwise for int DATA TYPES * unit - aka void * 'a - aka object (any type) primitive data types: * int, string etc. * type conversion: let b1 = byte 3 let b2 = byte 0xff let i1 = int 3.14 let g1 = 3L let g2 = int64 3.14 let f1 = 5f let f2 = float 5 let d = double 5 specialized data types: * tuples, type of cartesian product of parts ex. (1,2,3) is of type int*int*int, parts do not have to be the same type let t = (1, "abc", true) // construct let v1,v2,v3 = t // de-construct * options - nullable values * enums type MyEnum = | First = 0 | Second = 1 * discriminating unions (type unions) type IntList = | E -> int | T -> int * int | L -> IntListList let s = L([E(1);T((2,8));L(E(3);E(4))]) * type alias type Count = int * arrays let ar = [|1;2;3;4|] let a2 = ar.[1] let a23 = ar.[1..2] record: type Rect = { Wd: int; Ht: int; } * type inference let r1 = {Wd=4;Ht=5;} * explicit type declaration let r2 : Rect = {Wd=4;Ht=5;} * records can have calculated fields (members) lists: * [] - empty list * [1;2;3] * elements must be of the same type * :: - cons operator * @ - append operator (list to list) * .Head .Tail .IsEmpty .Length * List module supplies many higher-order functions ex List.map * comprehension syntax [2..10] is the same as [2;3;4;5;6;7;8;9;10] * comprehension syntax [2..3..11] is the same as [2;5;8;11] * comprehension syntax [for x in 2..5 -> x, x*x] is the same as [(2,4),(3,9),(4,16),(5,25)] FUNCTIONS let square x = x * x let add2 x y = x + y let swap (a,b) = (b,a) let t3 t = let _,_,x3 = t x3 let t3' (_,_,x3) = x3 let add xs x = x :: xs let rec ll (ls : 'a List) = if ls.Empty then 0 elsse 1 + (ll ls.Tail) let rec ll' ls = match ls with | [] -> 0 | x :: xs -> 1 + (ll' xs) let takei n ls = match n, ls with | 0,_ -> [] | _,[] -> [] | _, (x::xs) -> x :: (takei (n-1) xs) * curried - add2 above is of type int->int->int, when the function is called the first parameter is bound producing a new function that now the second parameter is bound to * this process of bindig parameters from left to right as they become available is called partial application, it allows creation of specialized versions of existing functions * functions are values and can be passed to or returned from functions * |> - piping, syntactic shortcut, feeding a parameter or the output of a function as parameter to another ex. [1;2;3;4] |> List.map (fun x -> (x,x)) * r |> l - append result of r to parameter list of l * >> and << - composition, ex "let fg = f >> g" then "fg par1" is the same as "(f (g par1))" RECURSIVE FUNCTIONS * for recursive functions add "rec" after "let", F# optimizes tail recursion so stack overflow will not occur let showVals() = let r = Random() let rec dl() = printfn "%A" r.next() Thread.Sleep(1000) dl() dl() * helper functions that are used in recursion can be incorporated using the AND keyword let rec funA() = funB() and funB() = funA() LAMBDA EXPRESSIONS * syntax: fun n -> n % 2 = 0 * lambda expressions are functions * lambda expression is a value let add' = fun x y -> x + y TAKING FUNCTIONS AS PARAMETERS let check item op = if op item then "OK" else "NG" printfn "%A" (check 5 (fun x -> x>3) printfn "%A" (check "how are you" (fun x -> x.Length>5) * may need type annotations let check' (item: 'a) (op: a' -> bool) : string = if op item then "OK" else "NG" CONSTRUCTING FUNCTIONS let add x y = x + y let add5 = add 5 * curried - 5 is captured into function definition as the first parameter, add5 is a function! * this is partial application - create new function by binding parameters FUNCTIONAL FUNCTIONS let rec filter f ls = match ls with | [] -> [] | x :: xs -> (if f x then [x] else []) @ (filter f xs) printfn "%A" (filter (fun x -> x < 10) [1;3;10;20]) let rec mapcar f ls = match ls with | [] -> [] | x :: xs -> f x :: (mapcar f xs) printfn "%A" (maplist (fun x -> x*x) [1;3;10;20]) let rec reduce f s ls = match ls with | [] -> [] | x :: xs -> reduce f (f s x) xs printfn "%A" (reduce (fun r v -> r + v) 0 [1;3;10;20]) printfn "%A" (+) 0 [1;3;10;20]) OUT-OF-THE-BOX MAPPING FUNCTIONS ex. map, fold, filter [1;2;3;4] |> List.map (fun x -> (x,x)) let data = [("Cats",4);("Dogs",5);("Mice",3);("Elephants",2)] let count = List.fold (fun acc (nm,x) -> acc+x) 0 data [("Cats",4);("Dogs",5);("Mice",3);("Elephants",2)] |> List.filter (fun (nm,x) -> nm.Length <= 4) let add acc item = acc + item // accumulator function [ for i in 1..5 -> i*i ] |> List.reduce add IMPORTANT EXAMPLE type Tree<'a> = | Node of 'a * Tree<'a> * Tree<'a> | Tip let UnionSample2() = let tree = Node(4, Node(2, Node(1, Tip, Tip), Node(6, Tip, Tip)), Node(6, Node(5, Tip, Tip), Node(7, Tip, Tip))) let rec InOrder t = match t with | Node(x,left,right) -> (InOrder left) @ [x] @ (InOrder right) | Tip -> [] let rec Height t = match t with | Node(x,left,right) -> 1 + (max (Height left) (Height right)) | Tip -> 0 printfn "The tree in order = %A" (InOrder tree) printfn "\nThe height of the tree = %d" (Height tree)